package de.koller.million.enc.engine;

import de.koller.million.enc.EncNode;
import de.koller.million.enc.EncServerRoot;
import de.koller.million.enc.engine.debug.AdminConsole;

public class Engine extends EncNode {

	private long time;
	
	private int cps;
	private int currCps;
	private long nextCps;
	
	private long nextLog;
	private long currCalcTime;
	private int currCalcStep;
	
	public final UserCommunication userCommunication = new UserCommunication();
	public final AdminConsole adminConsole = new AdminConsole();
	
	@Override
	public void generate( EncServerRoot root, Object... references ) {
		super.generate( root, references );
		
		this.addNode( userCommunication );
		this.addNode( adminConsole );
	}

	@Override
	protected void update( Object... refernces ) {
		super.update( refernces );
		
	}

	public final void loop() {
		
		long delta = 0;
		long lastTime = System.currentTimeMillis();
		
		while( true ) {
			long currtime = System.currentTimeMillis();
			delta = currtime - lastTime;
			lastTime = currtime;
			
			if( delta == 0 )
				continue;
			
			long ct = System.nanoTime();
			
			time = currtime;
			this.updateNode( delta );
			
			checkCps( currtime );
			log( currtime, System.nanoTime() - ct );
		}
	}
	
	private void log( long currtime, long calctime ) {
		currCalcTime += calctime;
		currCalcStep++;
		
		if( nextLog < currtime ) {
			double st = currCalcTime / currCalcStep;
			st /= 1_000_000;
			st = Math.round( st );
			st /= 1000;
			
			long space = Math.round( (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024. / 1024. );
			
			System.out.println( "10sec log: " + currCalcStep + " steps (=" + st
					+ "ms [" + currCalcStep/10 + "]) " + space + "MB" );
			currCalcTime = 0;
			currCalcStep = 0;
			nextLog = currtime + 10_000;
		}
	}
	
	private void checkCps( long currtime ) {
		if( nextCps < currtime ) {
			cps = currCps;
			currCps = 0;
			nextCps = currtime + 1_000;
		}

		currCps++;
	}
	
	public long getTime() {
		return time;
	}

	public int getCps() {
		return cps;
	}
	
}
